//
//  WYFWebViewProxyDelegate.m
//  NetEaseFinancial
//
//  Created by 吴玉峰 on 8/17/15.
//  Copyright (c) 2015 吴玉峰. All rights reserved.
//

#import "WYFWebViewProxyDelegate.h"

#import <objc/runtime.h>

static NSString *const CUSTOM_PROTOCOL_SCHEME = @"jscall";

@interface WYFWebViewProxyDelegate ()

@property (nonatomic, weak) id webViewDelegate;
@property (nonatomic, weak) NSBundle *resourceBundle;
@property (nonatomic, weak) UIWebView *webView;
@property (nonatomic, strong) NSMutableDictionary *javascriptInterfaces;

@end

@implementation WYFWebViewProxyDelegate

- (instancetype)initWithWebView:(UIWebView *)webView webViewDelegate:(NSObject<UIWebViewDelegate> *)webViewDelegate {
    return [self initWithWebView:webView webViewDelegate:webViewDelegate resourceBundle:nil];
}

- (instancetype)initWithWebView:(UIWebView *)webView
                webViewDelegate:(NSObject<UIWebViewDelegate> *)webViewDelegate
                 resourceBundle:(NSBundle *)bundle {
    if ((self = [super init])) {
        [self _platformSpecificSetup:webView webViewDelegate:webViewDelegate resourceBundle:bundle];
    }
    return self;
}

#pragma mark - init & dealloc

- (void)_platformSpecificSetup:(UIWebView *)webView
               webViewDelegate:(id<UIWebViewDelegate>)webViewDelegate
                resourceBundle:(NSBundle *)bundle {
    self.webView = webView;
    self.webViewDelegate = webViewDelegate;
    self.webView.delegate = self;
    self.resourceBundle = bundle;
}

- (void)dealloc {
    self.webView.delegate = nil;
    self.webView = nil;
    self.webViewDelegate = nil;
    self.javascriptInterfaces = nil;
}

- (void)addJavascriptInterface:(NSObject *)interface WithName:(NSString *)name {
    if (!self.javascriptInterfaces) {
        self.javascriptInterfaces = [[NSMutableDictionary alloc] init];
    }

    NSLog(@"addJavascriptInterface.name ============ %@", name);
    self.javascriptInterfaces[name] = interface;
}

#pragma mark - UIWebView Delegate

- (void)webViewDidFinishLoad:(UIWebView *)webView {
    if (webView != self.webView) {
        return;
    }

    __strong typeof(self.webViewDelegate) strongDelegate = self.webViewDelegate;
    if (strongDelegate && [strongDelegate respondsToSelector:@selector(webViewDidFinishLoad:)]) {
        [strongDelegate webViewDidFinishLoad:webView];
    }
}

- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
    if (webView != self.webView) {
        return;
    }

    __strong typeof(self.webViewDelegate) strongDelegate = self.webViewDelegate;
    if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:didFailLoadWithError:)]) {
        [strongDelegate webView:webView didFailLoadWithError:error];
    }
}

- (BOOL)webView:(UIWebView *)webView
    shouldStartLoadWithRequest:(NSURLRequest *)request
                navigationType:(UIWebViewNavigationType)navigationType {

    if (webView != self.webView) {
        return YES;
    }
    //    NSURL *url = [request URL];
    __strong typeof(self.webViewDelegate) strongDelegate = self.webViewDelegate;

    NSString *requestString = [[request URL] absoluteString];
    NSLog(@"shouldStartLoadWithRequest:%@", requestString);
    if ([requestString hasPrefix:@"tel:"]) {
        [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:requestString]];
        NSLog(@"dial:%@", requestString);

        return YES;
    }

    if ([requestString hasPrefix:CUSTOM_PROTOCOL_SCHEME]) {
        NSLog(@"%@", requestString);

        /*
         A sample URL structure:
         easy-js:__JavascriptBridge__:execute
         easy-js:__JavascriptBridge__:setResult
         */
        NSArray *components = [requestString componentsSeparatedByString:@":"];

        NSString *obj = (NSString *)[components objectAtIndex:1];
        NSString *method =
            [(NSString *)[components objectAtIndex:2] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

        NSLog(@"obj======= %@", obj);
        NSLog(@"method======= %@", method);

        // execute the interfacing method
        NSObject *interface = [self.javascriptInterfaces objectForKey:obj];

        SEL selector = NSSelectorFromString([method stringByAppendingString:@":"]);
        NSMethodSignature *sig = [[interface class] instanceMethodSignatureForSelector:selector];
        NSInvocation *invoker = [NSInvocation invocationWithMethodSignature:sig];
        invoker.selector = selector;
        invoker.target = interface;

        NSMutableArray *args = [[NSMutableArray alloc] init];

        if ([components count] > 3) {
            NSString *argsAsString =
                [(NSString *)[components objectAtIndex:3] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

            NSArray *formattedArgs = [argsAsString componentsSeparatedByString:@":"];
            for (NSUInteger i = 0, l = [formattedArgs count]; i < l; i++) {
                NSString *argStr = ((NSString *)[formattedArgs objectAtIndex:i]);

                NSString *arg = [argStr stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

                NSLog(@"arg ==== %@", arg);

                [args addObject:arg];
                [invoker setArgument:&arg atIndex:(i + 2)];
            }
        }
        [invoker invoke];

        // return the value by using javascript
        if ([sig methodReturnLength] > 0) {
            __autoreleasing NSString *retValue;
            [invoker getReturnValue:&retValue];

            if (retValue == NULL || retValue == nil) {
                [webView stringByEvaluatingJavaScriptFromString:@"EasyJS.retValue=null;"];
            } else {
                NSString* valueForJs = (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(
                    NULL, (CFStringRef)retValue, NULL, (CFStringRef) @"!*'();:@&=+$,/?%#[]", kCFStringEncodingUTF8));
                [webView
                    stringByEvaluatingJavaScriptFromString:[@"" stringByAppendingFormat:@"EasyJS.retValue=\"%@\";", valueForJs]];
            }
        }

        return NO;
    } else if (strongDelegate &&
               [strongDelegate respondsToSelector:@selector(webView:shouldStartLoadWithRequest:navigationType:)]) {
        return [strongDelegate webView:webView shouldStartLoadWithRequest:request navigationType:navigationType];
    } else {
        return YES;
    }
}

- (void)webViewDidStartLoad:(UIWebView *)webView {
    if (webView != self.webView) {
        return;
    }
    __strong typeof(self.webViewDelegate) strongDelegate = self.webViewDelegate;
    if (strongDelegate && [strongDelegate respondsToSelector:@selector(webViewDidStartLoad:)]) {
        [strongDelegate webViewDidStartLoad:webView];
    }
}


#pragma mark - call js
//执行js方法
- (void)executeJavasciptFunction:(NSString *)js {
    [self.webView stringByEvaluatingJavaScriptFromString:js];
}

@end
